﻿#include "ssXmlDBThread.h"
#include "log/ssLogThread.h"

namespace StarSeeker
{

ssXmlDBThread::ssXmlDBThread()
{
	m_log = false;
}

ssXmlDBThread::~ssXmlDBThread()
{
}

bool ssXmlDBThread::ReadAllCfg(const char* path)
{
	mysqlCfg cfg;
	mysqlCfg::iterator itr;
	if (path)
		cfg.SetPath(path);
	if (cfg.Read())
	{
		for (itr = cfg.MapBegin(); itr != cfg.MapEnd(); itr++)
		{
			m_queryMap[(u32)itr->first] = itr->second;
		}
		cfg.Clear();
		return InitQuery();
	}
	return false;
}

//准备查询语句
bool ssXmlDBThread::InitQuery()
{
	std::map<u32, mysqlCfgRow>::iterator itr;
	for (itr = m_queryMap.begin(); itr != m_queryMap.end(); ++itr)
	{
		if (itr->second.queryType.val & DB_RESULT_CLEAR)
			continue;

		i32 ret = 0;
		if (itr->second.outParam.val.size() == 1 && itr->second.inParam.val.size() == 1
			&& itr->second.outParam.val[0] == '$' && itr->second.inParam.val[0] == '$')
		{
			ret = m_mysqlQuery.PrepareQuery((u32)itr->second.id.val, itr->second.sql.val.c_str(), itr->second.queryType.val);
		}
		else
		{
			ret = m_mysqlQuery.PrepareQuery((u32)itr->second.id.val, itr->second.inParam.val.empty() ? 0 : itr->second.inParam.val.c_str(),
				itr->second.outParam.val.empty() ? 0 : itr->second.outParam.val.c_str(),
				itr->second.sql.val.c_str(), itr->second.queryType.val);
		}
		if (ret)
		{
			SS_LOG->Error(itr->second.sql.val.c_str());
			return false;
		}
	}
	return true;
}

void ssXmlDBThread::AddQuery(u32 id, const char * pIn, const char * pOut, const char * pSql, const i8 resultFlag)
{
	mysqlCfgRow tmp;
	tmp.id.val = id;
	tmp.inParam.val = pIn;
	tmp.outParam.val = pOut;
	tmp.sql.val = pSql;
	tmp.queryType.val = resultFlag;
	m_queryMap[id] = tmp;
}

mysqlCfgRow* ssXmlDBThread::GetCfg(u32 id)
{
	std::map<u32, mysqlCfgRow>::iterator itr = m_queryMap.find((i32)id);
	if (itr != m_queryMap.end())
	{
		return &itr->second;
	}
	return 0;
}

bool ssXmlDBThread::OnDBMsg(ssNetMsgHead* pHead, const char* pData, const u32 dataLen, u32 connectID)
{
	bool ret = true;
	mysqlCfgRow* pcfg = GetCfg(pHead->m_dwMsgID);
	if (pcfg)
	{
		i64 tsBegin = 0;
		i64 tsEnd = 0;
		if (m_log)
		{
			SS_LOG->PrintEx("[%d]%s", m_ThreadId, pcfg->sql.val.c_str());
		}
		if (m_queryInfo.m_enableInvokeRecord)
		{
			tsBegin = ssTime::GetTimeNowMS().i64p;
		}
		if (pcfg->queryType.val & DB_RESULT_NULL)
		{
			ret = OnDBMsgNullRecord(pcfg->id.val, pHead, pData, dataLen, connectID);
		}
		else if(pcfg->queryType.val & DB_RESULT_ONE)
		{
			ret = OnDBMsgOneRecord(pcfg->id.val, pHead, pData, dataLen, connectID);
		}
		else if (pcfg->queryType.val & DB_RESULT_MULTI)
		{
			ret = OnDBMsgMultiRecord(pcfg->id.val, pHead, pData, dataLen, connectID);
		}
		else if (pcfg->queryType.val & DB_RESULT_CLEAR)
		{
			OnDBMsgCleanBuffer();
		}
		if (m_queryInfo.m_enableInvokeRecord)
		{
			tsEnd = ssTime::GetTimeNowMS().i64p;
			m_queryInfo.RecordInfo(pcfg->id.val, tsEnd, tsBegin);
		}
	}
	return ret;
}

bool ssXmlDBThread::OnOtherMsg(ssMsg_s &m)
{
	if (m.msgID == SS_MSG_THREAD)
	{
		switch (m.subID)
		{
		case SS_DBEV_CLEAR_BUFFER:
			OnDBMsgCleanBuffer();
			break;
		case SS_DBEV_QUERY_INFO:
			PrintQueryInfo();
			break;
		default:
			break;
		}
	}
	return true;
}

void ssXmlDBThread::PrintQueryInfo()
{
	if (m_queryInfo.m_enableInvokeRecord)
	{
		m_queryInfo.ComputeRate();
		if (!m_queryInfo.m_infoOrder.empty())
		{
			f32 qps = (f32)m_queryInfo.m_total.count / ((f32)m_queryInfo.m_total.time/1000.0f);
			std::stringstream ss;
			ss << "T" << m_ThreadId << " QueryInfo: [" << "\"total\":\"" << m_queryInfo.m_total.vap << "," << m_queryInfo.m_total.count << "," << qps << "\"" << std::endl;
			for (size_t i = 0; i < m_queryInfo.m_infoOrder.size(); i++)
			{
				ss << "\"" << std::hex << m_queryInfo.m_infoOrder[i].id << "\":\"" << std::dec << m_queryInfo.m_infoOrder[i].vap << "," << m_queryInfo.m_infoOrder[i].count << "\"" << std::endl;
			}
			ss << "]";
			SS_LOG->PrintFile(ss.str().c_str());
		}
		SS_MEMZERO(&m_queryInfo.m_total, sizeof(ssInvokeInfo::InvokeRecord))
	}
}

}
